﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

using Wicresoft.SMS.Common;


namespace Wicresoft.SMS.OMSService
{
    public interface IOmsAgent
    {
        string GetServiceInfo();
        string GetUserInfo(string xmsUser);
        string DeliverXms(string xmsData);
        string SendXms(string xmsData);
        string GetContacts(string UserKey, string Password);
        string SetReminder(string Owner, string Mobile, string reminderData);

        string WriteLog(DateTime dt, string product, string type, string msg, string user);

        string GetGetEmailByCSL(string cil);

        bool CheckEmail(string email);

        string GetMobileByCSL(string csl);

        string GetCILByCSL(string csl);

        string GetCSLByCIL(string cil);

        UserInfo GetUserInfoByCSL(string csl);

        bool AuthUser(string username, string pwd);

        UserInfo GetUserInfoByCIL(string cil);
    }

    public class Agent : IOmsAgent
    {
        #region dependency

        IDataService _service = new DataService();

        #endregion


        #region IOmsAgent Members

        public string GetServiceInfo()
        {
            Logger.Info("GetServiceInfo"); 
            return LoadXML("serviceInfo.xml");
        }

        public string GetUserInfo(string xmsUser)
        {
            Logger.Info("GetUserInfo");
            Logger.Info(xmsUser);
            try{
                tXmsUser in_user = XmlDeserialize<tXmsUser>(xmsUser);
                OMSUser userInfo = _service.AuthoriseUser(in_user.userId, in_user.password);
                if (userInfo == null){
                    Logger.Info(string.Format("Access denied by {0} or password {1}",in_user.userId,in_user.password));
                    return LoadXML("invalidUser.xml");
                }

                string returnvalue = DataService.BuildUserRespose(userInfo);
                Logger.Info(string.Format("The user information returned is : {0}",returnvalue));
                return returnvalue;     
            }
            catch (Exception e){
                Logger.Error(e.ToString());
                return e.ToString();
            }
        }

        public string DeliverXms(string xmsData)
        {
            Logger.Info("DeliverXms");
            return SendXms(xmsData);
        }

        public string SendXms(string xmsData)
        {
            Logger.Info("SendXms");
            Logger.Info(xmsData);
            try{
                tXmsData xmsDataObj = XmlDeserialize<tXmsData>(xmsData);// xmsDataSerialize.Deserialize(xrd) as tXmsData;
                //only support sms , not support mms
                if (xmsDataObj.xmsHead.requiredService != "SMS_SENDER")
                    return DataService.BuildError("invalidFormat", true);

                //build address
                StringBuilder addresses = new StringBuilder();
                foreach (string add in xmsDataObj.xmsHead.to)
                {
                    addresses.Append(add);
                    addresses.Append(";");
                }
                string addressesstring = addresses.ToString();

                //build content
                StringBuilder contents = new StringBuilder();
                foreach (tContent content in xmsDataObj.xmsBody.content)
                {
                    if (content.contentType == "text/plain")
                        contents.Append(content.Value);
                }
                string contentsstring = contents.ToString();

                Logger.Info(
                    string.Format("{0} is trying to deliver to {1} with the content that : {2}", xmsDataObj.user.userId, addressesstring, contentsstring));

                string returnValue = _service.SendSMS(xmsDataObj.user.userId, xmsDataObj.user.password, contentsstring, addressesstring);
                Logger.Info(string.Format("The delivered information returned is : {0}", returnValue));
                return returnValue;
            }
            catch (Exception ex){
                Logger.Error(ex.ToString());
                return ex.ToString();
            }
        }

        /// <summary>
        /// return contacts string of the consider userkey
        /// password will be varified,if user is invalid , null will be return
        /// otherwise at least contactData will be return
        /// </summary>
        /// <param name="UserKey">(canbe id,alias,email)</param>
        /// <param name="Password">password</param>
        /// <returns></returns>
        public string GetContacts(string UserKey, string Password)
        {
            Logger.Info("GetContacts");
            try{
                contactData contacts = _service.GetContacts(UserKey, Password);
                if (contacts == null)
                    return string.Empty;
                return XmlSerializer<contactData>(contacts);
            }
            catch (Exception e){
                return e.ToString();
            }
        }

        public string SetReminder(string Owner, string Mobile, string reminderData)
        {
            Logger.Info("SetReminder");
            try{
                Logger.Info(reminderData);
                reminderData request = XmlDeserialize<reminderData>(reminderData);
                Logger.Info("set user mobile");
                if(_service.SetUserMobilePhone(request.user.Owner,request.user.Mobile) > 0) return string.Empty;
                Logger.Info("sync");
                _service.Sync(request.reminder, request.user.Owner);
                return "Success";
            }
            catch (Exception e){
                Logger.Info(e.ToString());
                return e.ToString();
            }

        }

        public string WriteLog(DateTime dt, string product, string type, string msg, string user)
        {
            try
            {
                _service.WriteLog(dt, product, type, msg, user);
                return "Success";
            }
            catch (Exception ex)
            {
                DBLog.Exception("Agent.WriteLog", ex);
                return ex.ToString();
            }
        }
        
        public string GetGetEmailByCSL(string csl)
        {
            try
            {
                return _service.GetGetEmailByCSL(csl);
            }
            catch (Exception ex)
            {
                DBLog.Exception("Agent.GetGetEmailByCSL", ex);
                return "";
            }
        }

        public string GetMobileByCSL(string csl)
        {
            try
            {
                return _service.GetMobileByCSL(csl);
            }
            catch (Exception ex)
            {
                DBLog.Exception("Agent.GetMobileByCSL", ex);
                return "";
            }
        }


        public string GetCILByCSL(string csl)
        {
            try
            {
                return _service.GetCILByCSL(csl);
            }
            catch (Exception ex)
            {
                DBLog.Exception("Agent.GetMobileByCSL", ex);
                return "";
            }
        }

        public bool CheckEmail(string email)
        {
            try
            {
                return _service.CheckEmail(email);
            }
            catch (Exception ex)
            {
                DBLog.Exception("Agent.CheckEmail", ex);
                return false;
            }
        }

        #endregion


        #region private region

        /// <summary>
        /// load the xml from filename
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        private string LoadXML(string filename)
        {
            StreamReader sr = new StreamReader(HttpContext.Current.Server.MapPath(filename), Encoding.Unicode);
            string xml = sr.ReadToEnd();
            sr.Dispose();
            return xml;
        }

        private static string XmlSerializer<T>(T serialObject) where T : class
        {
            XmlSerializer ser = new XmlSerializer(typeof(T));
            System.IO.MemoryStream mem = new MemoryStream();
            XmlTextWriter writer = new XmlTextWriter(mem, Encoding.Unicode);
            ser.Serialize(writer, serialObject);
            writer.Close();

            return Encoding.Unicode.GetString(mem.ToArray());
        }

        private static T XmlDeserialize<T>(string str) where T : class
        {
            XmlSerializer mySerializer = new XmlSerializer(typeof(T));
            StreamReader mem2 = new StreamReader(
                    new MemoryStream(System.Text.Encoding.Unicode.GetBytes(str)),
                    System.Text.Encoding.Unicode);

            return (T)mySerializer.Deserialize(mem2);
        }

        #endregion



        public UserInfo GetUserInfoByCSL(string csl)
        {            
            try
            {
                UserInfo ui = new UserInfo();
                ui.CIL = GetCILByCSL(csl);
                ui.CSL = csl;
                ui.Email = GetGetEmailByCSL(csl);
                ui.Mobile = GetMobileByCSL(csl);
                return ui;
            }
            catch (Exception ex)
            {
                DBLog.Exception("Agent.GetUserInfoByCSL ", ex);
                return null;
            }
        }


        public UserInfo GetUserInfoByCIL(string cil)
        {
            try
            {
                string csl = GetCSLByCIL(cil);
                UserInfo ui = new UserInfo();
                ui.CIL = GetCILByCSL(csl);
                ui.CSL = csl;
                ui.Email = GetGetEmailByCSL(csl);
                ui.Mobile = GetMobileByCSL(csl);
                return ui;
            }
            catch (Exception ex)
            {
                DBLog.Exception("Agent.GetUserInfoByCSL ", ex);
                return null;
            }
        }

        public bool AuthUser(string username, string pwd)
        {
            try
            {
                return _service.AuthUser(username, pwd);
            }
            catch (Exception ex)
            {
                DBLog.Exception("Agent.AuthUser", ex);
                return false;
            }
        }

        public string GetCSLByCIL(string cil)
        {
            try
            {
                return _service.GetCSLByCIL(cil);
            }
            catch (Exception ex)
            {
                DBLog.Exception("Agent.GetCSLByCIL ", ex);
                return "";
            }
        }
    }
}